using System;
using System.Text;
using System.Reflection;
using System.Collections.Generic;

namespace Crainiate.Data.Persistence.Providers
{
    //Events signatures for verifying and deploying assemblies, types and properties
    public delegate void DeployAssemblyHandler(object sender, DeployAssemblyEventArgs e);
    
    public delegate void PreValidateTypeEventHandler(object sender, PreValidateTypeEventArgs e);
    public delegate void PostValidateTypeEventHandler(object sender, PostValidateTypeEventArgs e);

    public delegate void PreDeployTypeHandler(object sender, PreDeployTypeEventArgs e);
    public delegate void PostDeployTypeHandler(object sender, PostDeployTypeEventArgs e);
    public delegate void DeployTypeExceptionHandler(object sender, DeployTypeExceptionEventArgs e);

    public delegate void AddTableEventHandler(object sender, AddTableEventInfo e);
    public delegate void ChangeTableEventHandler(object sender, ChangeTableEventInfo e);
    public delegate void ReferenceEventHandler(object sender, ReferenceEventInfo e);

    public class DeployAssemblyEventArgs
    {
        private Assembly _assembly;
        private DeploymentMode _deploymentMode;
        private DeploymentType _deploymentType;
        private bool _cancel;

        public DeployAssemblyEventArgs(Assembly assembly, DeploymentMode deploymentMode, DeploymentType deploymentType)
        {
            _assembly = assembly;
            _deploymentMode = deploymentMode;
            _deploymentType = deploymentType;
            _cancel = false;
        }

        public Assembly Assembly
        {
            get
            {
                return _assembly;
            }
        }

        public DeploymentMode DeploymentMode
        {
            get
            {
                return _deploymentMode;
            }
        }

        public DeploymentType DeploymentType
        {
            get
            {
                return _deploymentType;
            }
        }

        public bool Cancel
        {
            get
            {
                return _cancel;
            }
            set
            {
                _cancel = value;
            }
        }
    }

    public abstract class ValidateTypeEventArgs
    {
        //Property variables
        private Type _type;

        public ValidateTypeEventArgs(Type type)
        {
            _type = type;
        }

        public Type Type
        {
            get
            {
                return _type;
            }
        }
    }

    public class PreValidateTypeEventArgs: ValidateTypeEventArgs
    {
        //Property variables
        private bool _cancel;

        public PreValidateTypeEventArgs(Type type): base(type)
        {
        }

        public bool Cancel
        {
            get
            {
                return _cancel;
            }
            set
            {
                _cancel = value;
            }
        }
    }

    public  class PostValidateTypeEventArgs: ValidateTypeEventArgs
    {
        //Property variables
        private bool _changed;
        private bool _exists;

        public PostValidateTypeEventArgs(Type type): base(type)
        {
        }

        public bool Changed
        {
            get
            {
                return _changed;
            }
            set
            {
                _changed = value;
            }
        }

        public bool Exists
        {
            get
            {
                return _exists;
            }
            set
            {
                _exists = value;
            }
        }
    }


    public abstract class DeployTypeEventArgs
    {
        //Property variables
        private Type _type;
        private string _name;

        public DeployTypeEventArgs(Type type, string name)
        {
            _type = type;
            _name = name;
        }

        public Type Type
        {
            get
            {
                return _type;
            }
        }

        public string Name
        {
            get
            {
                return _name;
            }
        }
    }

    public class PreDeployTypeEventArgs: DeployTypeEventArgs
    {
        //Property variables
        private bool _cancel;

        public PreDeployTypeEventArgs(Type type, string name): base(type, name)
        {
            _cancel = false;
        }

        public bool Cancel
        {
            get
            {
                return _cancel;
            }
            set
            {
                _cancel = value;
            }
        }
    }

    public class PostDeployTypeEventArgs: DeployTypeEventArgs
    {
        //Property variables
        private string _script;

        public PostDeployTypeEventArgs(Type type, string name, string script): base(type, name)
        {
            _script = script;
        }

        public string Script
        {
            get
            {
                return _script;
            }
        }
    }

    public class DeployTypeExceptionEventArgs : DeployTypeEventArgs
    {
        //Property variables
        private string _script;
        private Exception _exception;

        public DeployTypeExceptionEventArgs(Type type, string name, string script, Exception e): base(type, name)
        {
            _script = script;
            _exception = e;
        }

        public string Script
        {
            get
            {
                return _script;
            }
        }

        public Exception Exception
        {
            get
            {
                return _exception;
            }
            set
            {
                _exception = value;
            }
        }
    }

    public class TableEventInfo
    {
        //Property variables
        private Type _type;
        private string _name;

        public TableEventInfo(Type type, string name)
        {
            _type = type;
            _name = name;
        }

        public Type Type
        {
            get
            {
                return _type;
            }
        }

        public string Name
        {
            get
            {
                return _name;
            }
        }
    }

    public class AddTableEventInfo: TableEventInfo
    {
        TableDefinition _definition;

        public AddTableEventInfo(Type type, string name, TableDefinition definition): base(type, name)
        {
            _definition = definition;
        }

        public TableDefinition TableDefinition
        {
            get
            {
                return _definition;
            }
        }
    }

    public class ChangeTableEventInfo: TableEventInfo
    {
        TableDefinition _definition;
        KeyDefinition _keyDefinition;
        TableModification _modification;

        public ChangeTableEventInfo(Type type, string name, TableDefinition definition, KeyDefinition keyDefinition, TableModification modification): base(type, name)
        {
            _definition = definition;
            _keyDefinition = keyDefinition;
            _modification = modification;
        }

        public TableDefinition TableDefinition
        {
            get
            {
                return _definition;
            }
        }

        public TableModification TableModification
        {
            get
            {
                return _modification;
            }
        }

        public KeyDefinition KeyDefinition
        {
            get
            {

                return _keyDefinition;
            }
        }
    }

    public class ColumnEventInfo: TableEventInfo
    {
        PropertyInfo _propertyInfo;
        string _columnName;

        public ColumnEventInfo(Type type, string name, PropertyInfo property, string columnName): base(type, name)
        {
            _propertyInfo = property;
            _columnName = columnName;
        }

        public PropertyInfo Property
        {
            get
            {
                return _propertyInfo;
            }
        }

        public string ColumnName
        {
            get
            {
                return _columnName;
            }
        }
    }

    public class ReferenceEventInfo: ColumnEventInfo
    {
        private Type _referenceType;
        PropertyInfo _referenceProperty;
        private string _referenceColumn;

        public ReferenceEventInfo(Type type, string name, PropertyInfo property, string columnName, Type referenceType, PropertyInfo referenceProperty, string referenceColumn): base(type,name,property,columnName)
        {
            _referenceType = referenceType;
            _referenceProperty = referenceProperty;
            _referenceColumn = referenceColumn;
        }

        public Type ReferenceType
        {
            get
            {
                return _referenceType;
            }
        }

        public PropertyInfo ReferenceProperty
        {
            get
            {
                return _referenceProperty;
            }
        }

        public string ReferenceColumn
        {
            get
            {
                return _referenceColumn;
            }
        }
    }
}
